package com.sanrxteam.upload.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;

import com.sanrxteam.upload.DAO.UploadPage;
import com.sanrxteam.upload.DB.SrtDb;

public class UploadServlet extends HttpServlet {
	
	
	// 上传文件存储目录
    private static final String UPLOAD_DIRECTORY = "/WEB-INF/upload";
  //上传时生成的临时文件保存目录
    private static final String TEMP_PATH ="/WEB-INF/temp";
    // 上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 1;  // 内存临界值 - 超过后将产生临时文件并存储于临时目录中
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 10; // 最大文件上传值
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 15; // 最大请求值 (包含文件和表单数据)

	public UploadServlet() {
		super();
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
//		String s_filmName = request.getParameter("query");  //电影名称
//		String s_Title = request.getParameter("text_title_input");  //字幕标题
//		String s_Language = request.getParameter("text_language");  //字幕语言
//		String s_Format = request.getParameter("text_type");  //字幕格式text_type
//		String s_Producer = request.getParameter("input_maker");  //制作人
//		String s_Checker = request.getParameter("input_checker");  //校订人
//		String s_Source = request.getParameter("text_way");  //字幕来源
//		String s_Comment = request.getParameter("other_says_text"); //备注  

		UploadPage uPage = new UploadPage();
		
		
//		//上传时生成的临时文件保存目录
//		String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
		File tmpFile = new File(TEMP_PATH);
		if (!tmpFile.exists()) {
			// 创建临时目录
			tmpFile.mkdir();
		} 
		
		String message = "";
		
		// 使用Apache文件上传组件处理文件上传步骤：
			// 1、创建一个DiskFileItemFactory工厂
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 设置工厂的缓冲区的大小，当上传的文件大小超过缓冲区的大小时，就会生成一个临时文件存放到指定的临时目录当中。
		factory.setSizeThreshold(MEMORY_THRESHOLD);// 设置缓冲区的大小为1M，如果不指定，那么缓冲区的大小默认是10KB
		// 设置上传时生成的临时文件的保存目录
		factory.setRepository(tmpFile);
		// 2、创建一个文件上传解析器
		ServletFileUpload upload = new ServletFileUpload(factory);
		// 监听文件上传进度
		upload.setProgressListener(new ProgressListener() {
			public void update(long pBytesRead, long pContentLength, int arg2) {
				System.out.println("文件大小为：" + pContentLength + ",当前已处理：" + pBytesRead);
				/**
				 * 文件大小为：14608,当前已处理：4096 文件大小为：14608,当前已处理：7367
				 * 文件大小为：14608,当前已处理：11419 文件大小为：14608,当前已处理：14608
				 */
			}
		});
		// 解决上传文件名的中文乱码
		upload.setHeaderEncoding("UTF-8");
		//3、判断提交上来的数据是否是上传表单的数据
		  if(!ServletFileUpload.isMultipartContent(request)){
			  //按照传统方式获取数据
			  return;
			  }
		// 解析request对象，并得到一个表单项的集合
		try {
			 //设置上传单个文件的大小的最大值，目前是设置为1024*1024字节，也就是10MB
            upload.setFileSizeMax(MAX_FILE_SIZE);
            //设置上传文件总量的最大值，最大值=同时上传的多个文件的大小的最大值的和，目前设置为15MB
            upload.setSizeMax(MAX_REQUEST_SIZE);
            //4、使用ServletFileUpload解析器解析上传数据，解析结果返回的是一个List<FileItem>集合，每一个FileItem对应一个Form表单的输入项
            List<FileItem> list = upload.parseRequest(request);
            int i = 1;
            for (FileItem item : list) {
				if (item.isFormField()) {
					
//				
					String fieldname = item.getFieldName();// 字段名
					String fieldvalue = item.getString("UTF-8");// 字段值
					if(fieldname.equals("query")) 
						uPage.setS_filmName(fieldvalue);
					if(fieldname.equals("text_title_input")) 
						uPage.setS_Title(fieldvalue);
					if(fieldname.equals("text_language")) 
						uPage.setS_Language(fieldvalue);
					if(fieldname.equals("text_type")) 
						uPage.setS_Format(fieldvalue);
					if(fieldname.equals("input_maker")) 
						uPage.setS_Producer(fieldvalue);
					if(fieldname.equals("input_checker")) 
						uPage.setS_Checker(fieldvalue);
					if(fieldname.equals("text_way")) 
						uPage.setS_Source(fieldvalue);
					if(fieldname.equals("other_says_text")) 
						uPage.setS_Comment(fieldvalue);
					
				} else {
					// 上传表单项
					//得到上传的文件名称，
                    String filename = item.getName();
                    System.out.println(filename);
                    if(filename==null || filename.trim().equals("")){
                        continue;
                    }
					uPage.setS_Path(processUploadField(item));
					System.out.println(uPage.getS_Path());
					item.delete();
					message = "文件上传成功";
				}
			}
          //把注册成功的用户对象保存在session中
            request.getSession().setAttribute("upage", uPage);
            //数据库写入操作
     /*       SrtDb srt = new SrtDb();
            try {
				srt.addSrt("用户名", uPage.getS_Path(), uPage.getS_filmName(), uPage.getS_Title(), uPage.getS_Language(), uPage.getS_Format(), uPage.getS_Producer(), 
						uPage.getS_Checker(), uPage.getS_Source(), uPage.getS_Comment(), "发布日期", "下载量");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}*/
            
            
            
            
          
			
			//跳转到注册成功页面
			//request.getRequestDispatcher("../info.jsp").forward(request,response);
			response.getWriter().write("<script>alert(message);</script>");
		} catch (FileUploadBase.FileSizeLimitExceededException e) {
			message = "上传文件大小超过10M";
			e.printStackTrace();
		} catch (FileUploadBase.SizeLimitExceededException e) {
			message = "上传文件总大小超过15M";
			e.printStackTrace();
		} catch (FileUploadException e) {
			e.printStackTrace();
		}
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	
	}
	
	
	
/**
 * 处理文件上传
 * @param item
 */
	private String processUploadField(FileItem item) {
		
	
		
		 //得到上传文件的保存目录，将上传的文件存放于WEB-INF目录下，不允许外界直接访问，保证上传文件的安全
        //String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
        String s_Path = null;
        try {
			String filename = item.getName();
			 //注意：不同的浏览器提交的文件名是不一样的，有些浏览器提交上来的文件名是带有路径的，如：  c:\a\b\1.txt，而有些只是单纯的文件名，如：1.txt
            //处理获取到的上传文件的文件名的路径部分，只保留文件名部分
            filename = filename.substring(filename.lastIndexOf("\\")+1);
            //得到上传文件的扩展名
            String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
            //如果需要限制上传的文件类型，那么可以通过文件的扩展名来判断上传的文件类型是否合法
            System.out.println("上传的文件的扩展名是："+fileExtName);
            //获取item中的上传文件的输入流
            InputStream in = item.getInputStream();
            //得到文件保存的名称
            String saveFilename = makeFileName(filename);
            //得到文件的保存目录
            String realSavePath = makePath(saveFilename);
            //创建一个文件输出流
            FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
            s_Path = realSavePath + "\\" + saveFilename;
          
            //创建一个缓冲区
            byte buffer[] = new byte[1024];
            //判断输入流中的数据是否已经读完的标识
            int len = 0;
            //循环将输入流读入到缓冲区当中，(len=in.read(buffer))>0就表示in里面还有数据
            while((len=in.read(buffer))>0){
                //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                out.write(buffer, 0, len);
            }
            //关闭输入流
            in.close();
            //关闭输出流
            out.close();
            //删除处理文件上传时生成的临时文件
            item.delete();
           // uPage.setS_Path(s_Path);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return s_Path;
		
	}
	/**
	 * 处理普通表单信息
	 * @param fileitem
	 */
/*	private void processFormField(FileItem fileitem,int i) {
		
		String query ;
		String text_title_input;
		String text_language;
		String text_type;
		String input_maker;
		String input_checker;
		String text_way;
		String other_says_text;
		try {
			String fieldname = fileitem.getFieldName();// 字段名
			String fieldvalue = fileitem.getString("UTF-8");// 字段值
			System.out.println(i);
			System.out.println(fieldname + "=" + fieldvalue);
			switch (i) {
			case 1:
					query = fieldvalue;
					uPage.setS_Comment(query);
					System.out.println(uPage.getS_Comment());
				break;
			case 2:
				if(fieldname.equals("text_title_input")){
					text_title_input = fieldvalue;
					uPage.setS_Title(text_title_input);
					System.out.println(uPage.getS_Title());
				}
				break;
			case 3:
				if(fieldname.equals("text_language")){
					text_language = fieldvalue;
					uPage.setS_Language(text_language);
				}
				break;
			case 4:
				if(fieldname.equals("text_type")){
					text_type = fieldvalue;
					uPage.setS_Format(text_type);
				}
				break;
			case 5:
				if(fieldname.equals("input_maker")){
					input_maker = fieldvalue;
					uPage.setS_Producer(input_maker);
				}
				break;
			case 6:
				if(fieldname.equals("input_checker")){
					input_checker = fieldvalue;
					uPage.setS_Checker(input_checker);
				}
				break;
			case 7:
				if(fieldname.equals("text_way")){
					text_way = fieldvalue;
					uPage.setS_Source(text_way);
				}
				break;
			case 8:
				if(fieldname.equals("other_says_text")){
					other_says_text = fieldvalue;
					uPage.setS_Comment(other_says_text);
				}
				break;
			default:
				break;
			}
			
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

	}*/
	/**
     * 为防止一个目录下面出现太多文件，要使用hash算法打散存储
    * @Method: makePath
    * @Description: 
    *
    * @param filename 文件名，要根据文件名生成存储目录
    * @param savePath 文件存储路径
    * @return 新的存储目录
    */ 
	 private String makePath(String filename){
	        //得到文件名的hashCode的值，得到的就是filename这个字符串对象在内存中的地址
	        int hashcode = filename.hashCode();
	        int dir1 = hashcode&0xf;  //0--15
	        int dir2 = (hashcode&0xf0)>>4;  //0-15
	        //构造新的保存目录
	        String dir = UPLOAD_DIRECTORY + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
	        //File既可以代表文件也可以代表目录
	        File file = new File(dir);
	        //如果目录不存在
	        if(!file.exists()){
	            //创建目录
	            file.mkdirs();
	        }
	        return dir;
	    }

	 /**
	    * @Method: makeFileName
	    * @Description: 生成上传文件的文件名，文件名以：uuid+"_"+文件的原始名称
	    * @param filename 文件的原始名称
	    * @return uuid+"_"+文件的原始名称
	    */ 
	    private String makeFileName(String filename){  //2.jpg
	        //为防止文件覆盖的现象发生，要为上传文件产生一个唯一的文件名
	        return UUID.randomUUID().toString() + "_" + filename;
	    }

}
